﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.IO;
using System.Collections;
using System.Windows.Forms;

namespace Level_Editor
{
    abstract class Actor
    {
        public String file;
        protected String spriteFile;
        public String name;
        protected int collision;
        public Image[] sprites;
        public Image[] actors;
        public int instances;
        public int instanceIndices;
        public int type;

        public static float xfactor(int angle)
        {
            switch (angle)
            {
                case 0:
                    return 1;
                case 1:
                    return (float)Math.Sqrt(3) / 2;
                case 2:
                    return 0.5f;
                case 3:
                    return 0;
                case 4:
                case 5:
                case 6:
                    return -xfactor(6 - angle);
                default:
                    return xfactor(12 - angle);
            }

        }

        public static float yfactor(int angle)
        {
            switch (angle)
            {
                case 0:
                    return 0;
                case 1:
                    return 0.5f;
                case 2:
                    return (float)Math.Sqrt(3) / 2;
                case 3:
                    return 1;
                case 4:
                    return (float)Math.Sqrt(3) / 2;
                case 5:
                    return 0.5f;
                case 6:
                    return 0;
                default:
                    return - yfactor(12 - angle);
            }
        }

        override public String ToString()
        {
            return name;
        }

        protected Actor(string self, string file, string name, string collision) 
        {
            try
            {
                this.file = self;
                this.spriteFile = file;
                this.name = name;
                this.collision = Convert.ToInt32(collision);
                sprites = new Image[12];
                actors = new Image[12];
                instances = 0;
                instanceIndices = 0;

                StreamReader myStream;

 	            if ((myStream = new StreamReader(file)) != null)
                {
                    spriteFile = file;

                    try
                    {
                        String line;

                        line = myStream.ReadLine();
                        Image imageFile = new Bitmap(Path.GetDirectoryName(file).Replace("Sprites", "") + line);

                        line = myStream.ReadLine(); // Absorb States
                        line = myStream.ReadLine(); // Absorb Name

                        int frames = Convert.ToInt32(myStream.ReadLine());

                        while (frames-- > 0)
                            line = myStream.ReadLine(); // Absorb durations

                        int bottom, height, width;

                        bottom = Convert.ToInt32(myStream.ReadLine()); // Read Bottom
                        height = Convert.ToInt32(myStream.ReadLine()); // Read Height
                        width = Convert.ToInt32(myStream.ReadLine()); // Read Width

                        for (int i = 0; i < 7; i++)
                        {
                            Rectangle crop = new Rectangle(i * width, imageFile.Height - (bottom + height), width, height);
                            sprites[i] = new Bitmap(imageFile).Clone(crop, System.Drawing.Imaging.PixelFormat.DontCare);
                        }

                        for (int i = 7; i < 12; i++)
                        {
                            sprites[i] = new Bitmap(sprites[12 - i]);
                            sprites[i].RotateFlip(RotateFlipType.RotateNoneFlipX);
                        }
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show("Unable to open " + file + ". Error: " + e.Message + " - " + e.TargetSite, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("Error creating actor. Error: " + e.Message + " - " + e.TargetSite);
            }
        }

        protected void genActors(int collision, int fear, int pounce, int length)
        {
            int diameter = Math.Max(collision, fear) * 2;
            diameter = Math.Max(diameter, pounce * 2);
            diameter = Math.Max(diameter, sprites[0].Height);
            diameter = Math.Max(diameter, sprites[0].Width);
            diameter = Math.Max(diameter, length);

            for (int i = 0; i < 12; i++)
            {
                actors[i] = new Bitmap(diameter + 1, diameter + 1);
                Graphics overlay = Graphics.FromImage(actors[i]);
                Brush myBrush;

                myBrush = new SolidBrush(Color.FromArgb(127, Color.Green));
                overlay.FillEllipse(myBrush, diameter / 2 - fear, diameter / 2 - fear, fear * 2, fear * 2);

                myBrush = new SolidBrush(Color.FromArgb(127, Color.Blue));
                overlay.FillEllipse(myBrush, diameter / 2 - collision, diameter / 2 - collision, collision * 2, collision * 2);

                overlay.DrawEllipse(new Pen(Color.Green), diameter / 2 - fear, diameter / 2 - fear, fear * 2, fear * 2);
                overlay.DrawEllipse(new Pen(Color.Blue), diameter / 2 - collision, diameter / 2 - collision, collision * 2, collision * 2);
                overlay.DrawEllipse(new Pen(Color.Red), diameter / 2 - pounce, diameter / 2 - pounce, pounce * 2, pounce * 2);

                overlay.DrawImage(sprites[i], diameter / 2 - sprites[i].Width / 2, diameter / 2 - sprites[i].Height / 2);
                
                if (length != 0)
                {
                    try
                    {
                        Obstacle curr = (Obstacle) this;

                        int center_x = sprites[0].Width / 2 + curr.center_x;
                        int center_y = sprites[0].Height / 2 + curr.center_y;

                        myBrush = new SolidBrush(Color.FromArgb(127, Color.Blue));

                        foreach (Obstacle.Circle circle in curr.circles)
                        {
                            overlay.FillEllipse(myBrush, center_x + circle.x[i] - circle.r, sprites[i].Height - center_y - circle.y[i] - circle.r - 1, circle.r * 2, circle.r * 2);
                            overlay.DrawEllipse(new Pen(Color.Blue), center_x + circle.x[i] - circle.r, sprites[i].Height - center_y - circle.y[i] - circle.r - 1, circle.r * 2, circle.r * 2);
                        }

                        foreach (Obstacle.Line line in curr.lines)
                        {
                            overlay.DrawLine(new Pen(Color.Blue, 2), center_x + line.x1[i], sprites[i].Height - center_y - line.y1[i] + 1, center_x + line.x2[i], sprites[i].Height - center_y - line.y2[i] + 1);
                        }
                    }
                    catch (Exception)
                    {
                    }

                }
            }
        }

        public static Actor loadActor(string file)
        {
            StreamReader myStream;
            string spriteFile;

            try
            {
                if ((myStream = new StreamReader(file)) != null)
                {
                    try
                    {
                        String line;

                        line = myStream.ReadLine();
                        spriteFile = Path.GetDirectoryName(file).Replace("Actors", "") + line;

                        Hashtable types = new Hashtable();
                        types.Add("Wolf", 0);
                        types.Add("Dog", 1);
                        types.Add("Sheep", 2);
                        types.Add("Obstacle", 3);
                        types.Add("Line", 4);

                        switch ((int)types[myStream.ReadLine()])
                        {
                            case 0:
                                return new Wolf(file, spriteFile, myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine());
                            case 1:
                                return new Dog(file, spriteFile, myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine());
                            case 2:
                                return new Sheep(file, spriteFile, myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine(), myStream.ReadLine());
                            case 3:
                                return new Obstacle(file, spriteFile, myStream.ReadLine(), ref myStream);
                            default:
                                throw new Exception("Unrecognizable type");
                        }
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show("Unable to open " + file + ". Error: " + e.Message + " - " + e.TargetSite, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return null;
                    }
                }
                else
                {
                    MessageBox.Show("Unable to open " + file + ". File does not exist.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return null;
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("Error creating Actor. Error: " + e.Message + " - " + e.TargetSite, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }
        }
    }
}
